package com.myk.game.heroscuffle.events;

import java.util.ArrayList;
import java.util.List;

/**
 * 游戏事件监听器
 */
public class GameEventListener<T extends GameEventBase> {

    private final List<EventRunBack<T>> runBackList = new ArrayList<>();
    private EventDataBack<T> dataBack = () -> null;

    /**
     * 添加一个运行回调，相当于定义了一个匿名方法
     * 外界调用该方法不需要依赖定义该方法的组件
     */
    public void addRunBack(EventRunBack<T> eventRunBack) {
        runBackList.add(eventRunBack);
    }

    /**
     * 移除某个运行回调
     */
    public void removeRunBack(EventRunBack<?> eventRunBack) {
        runBackList.remove(eventRunBack);
    }

    /**
     * 移除该模型中所有运行回调
     */
    public void removeAllRunBack() {
        runBackList.clear();
    }

    /**
     * 通知该模型上的所有运行回调依次在主线程运行，
     * 不需要关心回调方法在哪个组件里定义的
     */
    public void sendRun(T event) {
        List<EventRunBack<T>> safeList = new ArrayList<>(runBackList);
        for (EventRunBack<T> runBack : safeList) {
            event.setListenerAndRunBack(this, runBack);
            runBack.onRun(event);
            event.setListenerAndRunBack(null,null);
        }
    }

    /**
     * 设置数据回调
     * 将一个组件里获取私有数据的方法存放到该模型里
     * 外界想要获取这个组件的私有数据时，不需要依赖私有组件，只需要依赖该模型即可
     */
    public void setDataBack(EventDataBack<T> eventDataBack) {
        this.dataBack = eventDataBack;
    }

    /**
     * 设置数据回调返回null
     */
    public void setNullDataBack() {
        dataBack = () -> null;
    }

    /**
     * 同步方法返回的方式获取某个值，不关心数据来源
     */
    public T getDataSync() {
        return dataBack.onBack();
    }

    /**
     * 异步回调的方式获取某个数据，不关心数据来源
     */
    public void getDataAsync(EventRunBack<T> runBack) {
        T data = dataBack.onBack();
        runBack.onRun(data);
    }
}
